package com.credithc.customers.manager.service.impl;

import com.credithc.baseserv.core.codes.CoreCodes;
import com.credithc.baseserv.core.exception.BsException;
import com.credithc.baseserv.core.service.impl.BaseServiceImpl;
import com.credithc.baseserv.core.utils.UUIDUtils;
import com.credithc.baseserv.pageHelper.PageInfo;
import com.credithc.customers.base.codes.CustomerCodes;
import com.credithc.customers.base.mapper.SystemInfoMapper;
import com.credithc.customers.base.po.SystemInfoPo;
import com.credithc.customers.base.service.ICacheService;
import com.credithc.customers.manager.service.SystemInfoService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;
import tk.mybatis.mapper.entity.Example;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;


/**
 * @Title: 系统标识
 * @Author: zhq
 * @Date: 2018/12/14
 * @Description: com.credithc.customers.manager.service
 * @Version: V1.0.0
 */
@Service
public class SystemInfoServiceImpl extends BaseServiceImpl<SystemInfoPo, SystemInfoPo, SystemInfoPo> implements SystemInfoService {
    String PUBLIC_KEY = "RSAPublicKey";
    String PRIVATE_KEY = "RSAPrivateKey";
    @Autowired
    SystemInfoMapper systemInfoMapper;

    @Autowired
    private ICacheService cacheService;

    @Override
    public PageInfo<SystemInfoPo> getList(String systemSign, Integer pageNo, Integer pageSize) {
        if (pageNo == null) {
            pageNo = 1;
        }
        if (pageSize == null) {
            pageSize = 20;
        }
       /* List<SystemInfoPo> systemInfoPos = systemInfoMapper.selectAll();
        for (SystemInfoPo sp:systemInfoPos) {
            sp.setPrivateKey(null);
            sp.setPublicKey(null);
        }
        PageInfo<SystemInfoPo> poPageInfo = new PageInfo<>();
        poPageInfo.setList(systemInfoPos);
        poPageInfo.setTotalCount(systemInfoPos.size());*/
        try {
            Example example = new Example(SystemInfoPo.class);
            Example.Criteria criteria = example.createCriteria();
            if (StringUtils.isNotEmpty(systemSign)) {
                criteria.andEqualTo("systemSign", systemSign);
            }
            example.setOrderByClause("create_time DESC");
            PageInfo<SystemInfoPo> poPageInfo = this.queryPageResultByExample(example, pageNo, pageSize);
            return poPageInfo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BsException(CoreCodes.CORE_SYS_ERROR);
        }

    }

    @Override
    public void updateUrl(String sysId, String newUrl) {
        SystemInfoPo systemInfoPo = queryOne(sysId, SystemInfoPo.class);
        systemInfoPo.setServiceUrl(newUrl);
        updateById(systemInfoPo);
    }

    @Override
    public void updateSystemInfo(SystemInfoPo po, String id) {
        try {
            po.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            po.setId(id);
            this.updateByPrimaryKeySelective(po);
            cacheService.clearSystemInfo();
            cacheService.cacheSystemInfo();
        } catch (Exception e) {
            throw new BsException(CoreCodes.CORE_SYS_ERROR);
        }

    }

    @Override
    public void insert(SystemInfoPo po) {
        if (StringUtils.isEmpty(po.getSystemSign()) || StringUtils.isEmpty(po.getSystemName())) {
            throw new BsException(CustomerCodes.PARAM_VALIDATE_ERROR, "系统标识与系统名称为必填项");
        }
        try {
            String path = "/";
            Example example = new Example(SystemInfoPo.class);
            Example.Criteria criteria = example.createCriteria();
            if (StringUtils.isNotEmpty(po.getParentId())) {
                criteria.andEqualTo("systemSign", po.getParentId());
                PageInfo<SystemInfoPo> poPageInfo = this.queryPageResultByExample(example, 1, Integer.MAX_VALUE);
                if (poPageInfo.getList().size() > 0) {
                    path = StringUtils.isEmpty(poPageInfo.getList().get(0).getPath()) ? "/" : poPageInfo.getList().get(0).getPath()+"/";
                }
            } else {
                path += "/";
            }
            Map<String, String> stringStringMap = initKey();
            po.setSecretKey(UUIDUtils.getUUID());
            po.setPublicKey(stringStringMap.get(PUBLIC_KEY));
            po.setPrivateKey(stringStringMap.get(PRIVATE_KEY));
            po.setPath(path + po.getSystemSign());
            po.setId(UUIDUtils.getUUID());
            po.setCreateTime(new Timestamp(System.currentTimeMillis()));
            systemInfoMapper.insert(po);
            cacheService.clearSystemInfo();
            cacheService.cacheSystemInfo();
        } catch (Exception e) {
            throw new BsException(CoreCodes.CORE_SYS_ERROR);
        }
    }

    @Override
    public void deleteSystemById(String id) {
        this.deleteById(id);
        cacheService.clearSystemInfo();
        cacheService.cacheSystemInfo();
    }

    /**
     * 初始化一对公钥私钥
     *
     * @return
     * @throws NoSuchAlgorithmException
     */
    private Map<String, String> initKey() throws NoSuchAlgorithmException {
        String KEY_ALGORITHM = "RSA";

        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, String> keyMap = new HashMap<>(2);
        keyMap.put(PUBLIC_KEY, (((new BASE64Encoder()).encodeBuffer(publicKey.getEncoded()))).replace("\r\n", "").replace("\n",""));
        keyMap.put(PRIVATE_KEY, (((new BASE64Encoder()).encodeBuffer(privateKey.getEncoded()))).replace("\r\n", "").replace("\n",""));
        return keyMap;
    }

    @Override
    public PageInfo<SystemInfoPo> getDictList(String systemSign,String accessed) {
        try {
            Example example = new Example(SystemInfoPo.class);
            Example.Criteria criteria = example.createCriteria();
            if (StringUtils.isNotEmpty(systemSign)) {
                criteria.andEqualTo("systemSign", systemSign);
            }
            if (StringUtils.isNotEmpty(accessed)) {
                criteria.andEqualTo("accessed", 1);
            }
            example.setOrderByClause("create_time DESC");
            PageInfo<SystemInfoPo> poPageInfo = this.queryPageResultByExample(example, 1, 10000);
            return poPageInfo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BsException(CoreCodes.CORE_SYS_ERROR);
        }

    }

}
